package com.flutter_ecg.flutter_ecg.ecgapplication.utils;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * Created by pitt.
 */
public class VoicePlay {
    private final String TAG = "VoicePlay";
    private static final String RIFF_HEADER = "RIFF";
    private static final String WAVE_HEADER = "WAVE";
    private static final String FMT_HEADER = "fmt ";
    private static final String DATA_HEADER = "data";

    private static final int HEADER_SIZE = 44;

    private static final String CHARSET = "ASCII";

    private boolean canPlayVoice = true;


    private int minBufSize = 0;
    private AudioTrack m_audioTrackPlayer;
    private static final int SAMPLE_RATE_HZ = 44100;
    private static final int CHANNEL_NUM = AudioFormat.CHANNEL_OUT_MONO;
    private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;

    private Thread playThread;
    private PlayVoice playVoice;
    private boolean isPlaying = false;

    private boolean isCanPlayVoice = true;

    public VoicePlay() {
        init();
    }

    /**
     * 用于静音模式
     * @param isCanPlayVoice
     */
    public void setTag(boolean isCanPlayVoice) {
        this.isCanPlayVoice = isCanPlayVoice;
    }

    public void playVoice(InputStream in) {
        if (!isCanPlayVoice) return;
        if (m_audioTrackPlayer == null) {
            init();
        }
        isPlaying = true;
        playVoice = new PlayVoice(in);
        playThread = new Thread(playVoice);
        playThread.start();
    }

    public void stop() {
        if (m_audioTrackPlayer == null) return;
        if (isPlaying) {
            m_audioTrackPlayer.pause();
            m_audioTrackPlayer.flush();
//            m_audioTrackPlayer.release();
        }
        playThread = null;
        playVoice = null;
        isPlaying = false;
    }


    private void init() {

        minBufSize = 2 * AudioTrack.getMinBufferSize(SAMPLE_RATE_HZ, CHANNEL_NUM, AUDIO_FORMAT);
        m_audioTrackPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE_HZ, CHANNEL_NUM, AUDIO_FORMAT, minBufSize, AudioTrack.MODE_STREAM);
        m_audioTrackPlayer.setStereoVolume((float) 1.0, (float) 1.0);
    }


    public synchronized int getDataSize(InputStream wavStream) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(HEADER_SIZE);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        wavStream.read(buffer.array(), buffer.arrayOffset(), buffer.capacity());
        buffer.rewind();
        buffer.position(buffer.position() + 20);
        int format = buffer.getShort();
        int channels = buffer.getShort();
        int rate = buffer.getInt();
        buffer.position(buffer.position() + 6);
        int bits = buffer.getShort();
        int dataSize = 0;
        while (buffer.getInt() != 0x61746164) { // "data" marker
            int size = buffer.getInt();
            wavStream.skip(size);

            buffer.rewind();
            wavStream.read(buffer.array(), buffer.arrayOffset(), 8);
            buffer.rewind();
        }
        dataSize = buffer.getInt();
//        Log.i("DataInfoPlay", " format =" + format + " channels =" + channels + " rate =" + rate + " bits = " + bits + " dataSize = " + dataSize);
        return dataSize;
    }

    public class PlayVoice implements Runnable {
        private InputStream inputStream;

        PlayVoice(InputStream inputStream) {
            this.inputStream = inputStream;
        }

        @Override
        public void run() {
            int i = 0;
            try {
                i = getDataSize(inputStream);
                byte[] data = readWavPcm(i, inputStream);
                m_audioTrackPlayer.play();
                m_audioTrackPlayer.write(data, 0, i);
                m_audioTrackPlayer.stop();
                if (endPlay != null) {
                    endPlay.end();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    public EndPlay endPlay;

    public void setEndPlay(EndPlay endPlay) {
        this.endPlay = endPlay;
    }

    public interface EndPlay {
        void end();
    }

    public synchronized static byte[] readWavPcm(int dataSize, InputStream stream)
            throws IOException {
        byte[] data = new byte[dataSize];
        stream.read(data, 0, data.length);
        return data;
    }
}
